/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package edu.chl.angholt.bookproject.db;

import edu.chl.angholt.bookproject.db.entity.Author;
import edu.chl.angholt.bookproject.db.entity.Author_;
import edu.chl.angholt.bookproject.db.entity.Book;
import edu.chl.angholt.bookproject.db.entity.Book_;
import edu.chl.angholt.bookproject.db.exception.NonexistentEntityException;
import java.util.Collections;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.NoResultException;
import javax.persistence.Query;
import javax.persistence.TypedQuery;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Root;

/**
 *
 * @author Jonas
 * Controller class for the Author entity
 */
public class AuthorJpaCtrl extends EntityJpaCtrl<Author> {

    public AuthorJpaCtrl(EntityManagerFactory emf) {
        super(emf);
    }

    /**
     * Get a list of all books written by the author specified
     * @param name The name of the author
     * @return A list of books
     */
    public List<Book> getBooksByAuthor(String name) {
        EntityManager em = emf.createEntityManager();
        CriteriaBuilder builder = em.getCriteriaBuilder();
        CriteriaQuery<Book> query = builder.createQuery(Book.class);
        Root<Book> a = query.from(Book.class);
        query.where(builder.equal(a.get(Book_.author).get(Author_.name), name));
        query.select(a);
        TypedQuery<Book> tq = em.createQuery(query);
        List<Book> books = tq.getResultList();

        em.close();
        return books;

    }

    /**
     * Remove an author from the database
     * @param id The Id of the author to remove
     * @throws NonexistentEntityException If no author with that Id can be found
     */
    @Override
    public void destroy(Long id) throws NonexistentEntityException {
        EntityManager em = emf.createEntityManager();
        EntityTransaction tx = em.getTransaction();


        tx.begin();
        Author a = em.find(Author.class, id);

        if (a == null) {
            throw new NonexistentEntityException("Can not remove entity because it does not exist");
        }


        em.remove(a);
        tx.commit();

        em.close();
    }

    /**
     * Find the specified author
     * @param id The id of the author to find
     * @return The found author
     */
    @Override
    public Author findEntity(Long id) {
        EntityManager em = emf.createEntityManager();
        return em.find(Author.class, id);
    }

    /**
     * Finds all authors in the database
     * @return A list of all authors in the database
     */
    @Override
    public List<Author> findEntities() {
        EntityManager em = emf.createEntityManager();
        CriteriaBuilder builder = em.getCriteriaBuilder();

        CriteriaQuery<Author> query = builder.createQuery(Author.class);
        Root<Author> a = query.from(Author.class);

        query.select(a);

        TypedQuery<Author> tq = em.createQuery(query);
        List<Author> authors = tq.getResultList();
        return authors;
    }

    /**
     * Finds a subset of authors from the database.
     * @param maxResults The maximum number of authors to find
     * @param firstResult The position of the first author to find
     * @return A list of the found authors
     */
    @Override
    public List<Author> findEntities(int maxResults, int firstResult) {
        EntityManager em = emf.createEntityManager();
        CriteriaBuilder builder = em.getCriteriaBuilder();

        CriteriaQuery<Author> query = builder.createQuery(Author.class);
        Root<Author> a = query.from(Author.class);

        query.select(a);

        TypedQuery<Author> tq = em.createQuery(query);
        tq.setFirstResult(firstResult);
        tq.setMaxResults(maxResults);
        List<Author> authors = tq.getResultList();
        return authors;
    }

    /**
     * 
     * @return The number of authors in the database
     */
    @Override
    public int getEntityCount() {
        return findEntities().size();
    }

    /**
     * Looks up an author by name
     * @param name The name of the author to find
     * @return The author with the specified name
     */
    public Author findAuthor(String name) {
        EntityManager em = emf.createEntityManager();

        CriteriaBuilder builder = em.getCriteriaBuilder();

        CriteriaQuery<Author> query = builder.createQuery(Author.class);
        Root<Author> a = query.from(Author.class);

        query.select(a).where(builder.equal(a.get(Author_.name), name));

        TypedQuery<Author> tq = em.createQuery(query);

        Author author = null;
        try {
            author = tq.getSingleResult();
        } catch (NoResultException e) {
            return null;
        }
        return author;
    }

  /**
     * Looks up an author by name
     * @param name The name of the author to find
     * @return The author with the specified name
     */
    public List<Author> findAuthorLike(String patern) {
        EntityManager em = emf.createEntityManager();
        CriteriaBuilder builder = em.getCriteriaBuilder();
        patern = "%"+patern+"%";
        CriteriaQuery<Author> query = builder.createQuery(Author.class);
        Root<Author> a = query.from(Author.class);

        query.select(a).where(builder.like(a.get(Author_.name), patern));

        TypedQuery<Author> tq = em.createQuery(query);

        List<Author> authors = tq.getResultList();
        return authors;
    }
    
        public void updateBook(Author author)throws NonexistentEntityException {
        EntityManager em = emf.createEntityManager();
  
        try {
            em.getTransaction().begin();

            Author a = findEntity(author.getAuthorId());
            a.setName(author.getName());
            a.setBiography(author.getBiography());
            a.setCountry(author.getCountry());
            a.setWebSite(author.getWebSite());
            //update
            em.merge(a);
            em.getTransaction().commit();
            
        } catch (Exception e) {
            System.out.println(e.getMessage());
             throw new NonexistentEntityException("Can not update entity");
        } finally {
            em.close();
        }
    }
}
